package com.sduept.nwld.dataserver.controller.message;

import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.component.message.model.MessageTypeDTO;
import com.sduept.generator.ObjectId;
import com.sduept.message.entity.MessageReceiveConfig;
import com.sduept.message.entity.MessageType;
import com.sduept.message.manager.MessageReceiveConfigManager;
import com.sduept.message.manager.MessageTypeManager;
import com.sduept.nwld.dataserver.manager.message.MessageReceiverManager;
import com.sduept.nwld.dataserver.manager.message.PersonnelMessageConfigureManager;
import com.sduept.nwld.dataserver.model.library.MessageReceiver;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import com.sduept.permission.entity.DepartmentEntityBean;
import com.sduept.permission.entity.PersonnelEntityBean;
import com.sduept.permission.manager.DepartManager;
import com.sduept.permission.manager.PersonnelManager;
import lombok.extern.slf4j.Slf4j;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.sql.SQLException;
import java.util.*;
@Slf4j
@Named
@ViewScoped
public class AdminMobileMessController extends AbstractController {
	/**
	 * 
	 */
	private static final long serialVersionUID = 7631748627889051005L;
	@Autowired
	private DepartManager dm;
	@Autowired
	private PersonnelMessageConfigureManager personMa;
	@Autowired
	private MessageReceiverManager recMa;
	@Autowired
	private MessageReceiveConfigManager relationManager;
	@Autowired
	private MessageReceiverManager receiverManager;
	@Autowired
	private MessageTypeManager typeManager;
	@Autowired
	private PersonnelManager pm;

	private TreeNode root;
	private TreeNode selectedNode = null;
	private DepartmentEntityBean currentDept;
	private PersonnelEntityBean currentPerson;
	private List<PersonnelEntityBean> personnels = new ArrayList<PersonnelEntityBean>();
	private Map<String, TreeNode> departmentMap = new HashMap<String, TreeNode>();// 存储组织机构树的部门节点 部门id-部门节点
	private Map<String, MessageReceiver> messageReceiverMap = new HashMap<String, MessageReceiver>();
	private Map<String, MessageType> messageTypeMap = new HashMap<String, MessageType>();
	private List<MessageReceiveConfig> messageConfigList = new ArrayList<MessageReceiveConfig>();
	private Set<String> recString = new HashSet<String>();// 接收方式的中文描述
	private List<MessageTypeDTO> allTypeList = new ArrayList<MessageTypeDTO>();

	private String receiveChangeValue = null; // 指示当前操作是增加还是删除

	@PostConstruct
	public void init() {
		initMessageReceiverMap();
		initMessageTypeMap();
		initOrgTree();
	}

	/**
	 * 加载所有的消息接收类型，并放在messageReceiverMap中 messageReceiverMap：<id,MessageReceiver>
	 */
	private void initMessageReceiverMap() {
		List<MessageReceiver> receivers = receiverManager.listAll();
		for (MessageReceiver m : receivers) {
			messageReceiverMap.put(m.getId(), m);
			recString.add(m.getId());
		}

	}

	/**
	 * 1.加载所有消息类型，并放在messageTypeMap中 messageTypeMap：<id,MessageType>
	 * 2.加载allTypeList
	 */
	public void initMessageTypeMap() {
		allTypeList.clear();
		List<MessageType> types = typeManager.findAll();
		for (MessageType t : types) {
			messageTypeMap.put(t.getId(), t);
			MessageTypeDTO n = new MessageTypeDTO();
			n.setMsgType(t);
			allTypeList.add(n);
		}
	}

	/**
	 * 初始化组织机构树
	 */
	private void initOrgTree() {
		try {
			root = new LibTreeNode("Root", null);
			List<DepartmentEntityBean> departments = dm.findRootDepts();
			for (DepartmentEntityBean s : departments) {
				LibTreeNode n = new LibTreeNode("dept", s, root);
				departmentMap.put(s.getId(), n);// 存储节点
				List<DepartmentEntityBean> ds = dm.getDepartmentsByParent(s.getId());
				if (ds != null && ds.size() > 0) {
					for (DepartmentEntityBean d : ds) {
						TreeNode treeNode = new LibTreeNode("dept", d, n);
						departmentMap.put(d.getId(), treeNode);// 存储节点
					}
				}
				List<PersonnelEntityBean> personnels = dm.findDeptPersonnels(s.getId());
				if (personnels != null && personnels.size() > 0) {
					for (PersonnelEntityBean p : personnels) {
						new DefaultTreeNode("personnel", p, n);
					}
				}
				n.setExpanded(true);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 组织机构树节点选择事件
	 */
	public void onNodeSelect(NodeSelectEvent event) {
		selectedNode = event.getTreeNode();
		loadPersonnelList(selectedNode);
		List<String> ids = new ArrayList<String>();
		messageConfigList.clear();
		for (PersonnelEntityBean p : personnels) {
			ids.add(p.getCode());
		}
		if (ids.size() > 0) {
			messageConfigList = relationManager.findByReceiverIds(ids);
			log.info(String.valueOf(messageConfigList.size()));
		}
	}

	/**
	 * 加载员工信息列表
	 * @param selectedNode
	 * 1.如果选中节点为“dept”，则需要查到这个组织机构下的所有人 
	 * 2.如果选中的节点为“personnel”，则把这个人员的id，set进ids这个list中
	 * 3.最终调用queryByPerson(List<String> ids) 方法，结果集为messageConfigList
	 */
	public void loadPersonnelList(TreeNode selectedNode) {
		personnels.clear();
		if ("dept".equals(selectedNode.getType())) {
			currentDept = (DepartmentEntityBean) selectedNode.getData();
			List<PersonnelEntityBean> beans = dm.findDeptPersonnels(currentDept.getId());
			personnels.addAll(beans);
			currentPerson = null;
		} else if ("personnel".equals(selectedNode.getType())) {
			currentPerson = (PersonnelEntityBean) selectedNode.getData();
			PersonnelEntityBean personnel = pm.findPersonnelById(currentPerson.getId());
			personnels.add(personnel);
			currentDept = null;
		}
	}

	/**
	 * 组织机构树节点展开事件
	 * 
	 * @param event
	 */
	public void onNodeExpand(NodeExpandEvent event) {
		TreeNode selected = event.getTreeNode();
		selected.getChildren().clear();
		if (selected.getType().equals("dept")) {
			DepartmentEntityBean dept = (DepartmentEntityBean) selected.getData();
			try {
				List<DepartmentEntityBean> ds = dm.getDepartmentsByParent(dept.getId());
				if (ds != null && ds.size() > 0) {
					for (DepartmentEntityBean d : ds) {
						TreeNode treeNode = new LibTreeNode("dept", d, selected);
						departmentMap.put(d.getId(), treeNode);// 存储节点
					}
				}
				personnels = dm.findDeptPersonnels(dept.getId());
				if (personnels != null && personnels.size() > 0) {
					for (PersonnelEntityBean p : personnels) {
						new DefaultTreeNode("personnel", p, selected);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 根据messageType的id获取messageType的描述
	 * messageTypeMap：初始加载时，将所有数据库中的messageType都加载进去了
	 * <id,实体>
	 * @param id
	 * @return Description
	 */
	public String getTypeDescription(String id) {
		return messageTypeMap.get(id).getDescription();
	}

	/**
	 * 根据MessageReceive的id获取MessageReceive的描述
	 * messageReceiverMap：初始加载时，将所有数据库中的messageReceiverMap都加载进去了
	 * <id,实体>
	 * @param id
	 * @return Description
	 */
	public String getReceiveDescription(String id) {
		if(messageReceiverMap.size()<1) {
			return "";
		}else {
			return messageReceiverMap.get(id).getName();
		}
		
	}

	/**
	 * 配置消息接收
	 * 1.先判断当前是否有选中节点；如果没有，提示未选中
	 * 2.如果选中的节点是部门，则循环遍历所有人员，根据配置选取
	 * 3.如果选中的节点是人，则直接配置
	 * 保存逻辑：
	 * 1.拿到dto
	 * 2.循环保存
	 */
	public void saveConfigMessage() {
		if (selectedNode != null) {
			if ("dept".equals(selectedNode.getType())) {
				currentDept = (DepartmentEntityBean) selectedNode.getData();
				deleteRelationsByDepartment(currentDept);
				List<PersonnelEntityBean> beans = dm.findDeptPersonnels(currentDept.getId());
				if (beans.size() > 0) {
					for (PersonnelEntityBean person : beans) {
						saveConfigMessageByPerson(person.getCode(), allTypeList);
					}
				} else {
					addErrorMessage("该组织机构下无直属人员 ，请选择有效组织机构");
				}
			} else if ("personnel".equals(selectedNode.getType())) {
				currentPerson = (PersonnelEntityBean) selectedNode.getData();
				deleteRelationsByPerson(currentPerson);
				PersonnelEntityBean personnel = pm.findPersonnelById(currentPerson.getId());
				saveConfigMessageByPerson(personnel.getCode(), allTypeList);
			}
			queryBySelectNode();
		} else {
			addErrorMessage("请选中人或组织机构进行配置");
		}
	}

	/**
	 * 根据人员保存关系
	 * @param code
	 * @param dtos
	 */
	private void saveConfigMessageByPerson(String code, List<MessageTypeDTO> dtos) {
		List<MessageReceiveConfig> relations = new ArrayList<>();
		for (MessageTypeDTO dto : dtos) {
			for (String receiver : dto.getRec()) {
				MessageReceiveConfig relation = new MessageReceiveConfig();
				relation.setReceiverId(code);
				relation.setMsgSenderId(receiver);
				relation.setMsgTypeId(dto.getMsgType().getId());
				relation.setId(ObjectId.get().toString());
				relations.add(relation);
			}
		}
		try {
			relationManager.save(relations);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 组织机构树节点选择事件
	 */
	private void queryBySelectNode() {
		loadPersonnelList(selectedNode);
		List<String> ids = new ArrayList<String>();
		messageConfigList.clear();
		for (PersonnelEntityBean p : personnels) {
			ids.add(p.getCode());
		}
		if (ids.size() > 0) {
			messageConfigList = relationManager.findByReceiverIds(ids);
		}
	}

	/**
	 * 根据部门删除这个部门下所有人员的消息接收配置relations
	 * @param department
	 */
	private void deleteRelationsByDepartment(DepartmentEntityBean department) {
		List<MessageReceiveConfig> datas = findRelationsByDepartment(department);
		if (datas != null && datas.size() > 0) {
			relationManager.delete(datas);
		}

	}

	/**
	 * 根据人员删除消息接收配置relations
	 * @param person
	 */
	private void deleteRelationsByPerson(PersonnelEntityBean person) {
		List<MessageReceiveConfig> datas = findRelationsByPerson(person);
		relationManager.delete(datas);
	}

	/**
	 * 根据部门查询这个部门下所有人员的消息接收配置relations
	 * @param department
	 * @return
	 */
	private List<MessageReceiveConfig> findRelationsByDepartment(DepartmentEntityBean department) {
		List<PersonnelEntityBean> beans = dm.findDeptPersonnels(department.getId());
		List<String> ids = new ArrayList<>();
		for (PersonnelEntityBean p : beans) {
			ids.add(p.getCode());
		}
		if (ids.size() > 0) {
			return relationManager.findByReceiverIds(ids);
		} else {
			return null;
		}
	}

	/**
	 * 根据person查询reations
	 * @param person
	 * @return
	 */
	private List<MessageReceiveConfig> findRelationsByPerson(PersonnelEntityBean person) {
		List<String> ids = new ArrayList<>();
		ids.add(person.getCode());
		return relationManager.findByReceiverIds(ids);
	}

	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

	public TreeNode getSelectedNode() {
		return selectedNode;
	}

	public void setSelectedNode(TreeNode selectedNode) {
		this.selectedNode = selectedNode;
	}

	public List<PersonnelEntityBean> getPersonnels() {
		return personnels;
	}

	public void setPersonnels(List<PersonnelEntityBean> personnels) {
		this.personnels = personnels;
	}

	public Map<String, TreeNode> getDepartmentMap() {
		return departmentMap;
	}

	public void setDepartmentMap(Map<String, TreeNode> departmentMap) {
		this.departmentMap = departmentMap;
	}

	public List<MessageReceiveConfig> getMessageConfigList() {
		return messageConfigList;
	}

	public void setMessageConfigList(List<MessageReceiveConfig> messageConfigList) {
		this.messageConfigList = messageConfigList;
	}

	public DepartmentEntityBean getCurrentDept() {
		return currentDept;
	}

	public void setCurrentDept(DepartmentEntityBean currentDept) {
		this.currentDept = currentDept;
	}

	public PersonnelEntityBean getCurrentPerson() {
		return currentPerson;
	}

	public void setCurrentPerson(PersonnelEntityBean currentPerson) {
		this.currentPerson = currentPerson;
	}

	public Set<String> getRecString() {
		return recString;
	}

	public void setRecString(Set<String> recString) {
		this.recString = recString;
	}

	public List<MessageTypeDTO> getAllTypeList() {
		return allTypeList;
	}

	public void setAllTypeList(List<MessageTypeDTO> allTypeList) {
		this.allTypeList = allTypeList;
	}

}
